/***************************************************************************
 *                                                                         *
 * Copyright (c) 2007 - 2009 Nuvoton Technology Corp. All rights reserved.*
 *                                                                         *
 ***************************************************************************/
 
/****************************************************************************
 * 
 * FILENAME
 *     NUC900_VPOST_SAMSUNG_80_18BIT.c
 *
 * VERSION
 *     0.1 
 *
 * DESCRIPTION
 *
 *
 *
 *
 * DATA STRUCTURES
 *     None
 *
 * FUNCTIONS
 *
 *
 *     
 * HISTORY
 *     2005.03.16		Created by Shih-Jen Lu
 *
 *
 * REMARK
 *     None
 *
 *
 **************************************************************************/
#include "wblib.h"
#include "NUC900_VPOST_Regs.h"
#include "NUC900_VPOST.h"
#ifdef	HAVE_SAMSUNG_80_18BIT



static VPOST_T	_tSAMSUNG_80_18BIT;

static void Delay(int nCnt)
{
	volatile int  loop;
	for (loop=0; loop<nCnt; loop++);
}


static VOID vpostDisp_F_ISR(void)
{
    outpw(REG_LCM_INT_CS,inpw(REG_LCM_INT_CS) | VPOSTB_DISP_F_STATUS);
    //vpostVATrigger();
    _tSAMSUNG_80_18BIT.fnDisplayCallBack(0,0);
}
static VOID vpostUNDERRUN_ISR(void)
{
	outpw(REG_LCM_INT_CS,inpw(REG_LCM_INT_CS) | VPOSTB_UNDERRUN_INT);
}

static VOID vpostBUS_ERROR_ISR(void)
{
	outpw(REG_LCM_INT_CS,inpw(REG_LCM_INT_CS) | VPOSTB_BUS_ERROR_INT);
}
#ifdef ECOS
static cyg_uint32 vpostIntHandler(cyg_vector_t vector, cyg_addrword_t data)
#else
static VOID vpostIntHandler(void)
#endif
{
   /* clear VPOST interrupt state */
   UINT32 uintstatus;
   
   uintstatus = inpw(REG_LCM_INT_CS);
   if (uintstatus & VPOSTB_DISP_F_STATUS)  
      vpostDisp_F_ISR();
   else if (uintstatus & VPOSTB_UNDERRUN_INT)
      vpostUNDERRUN_ISR();
   else if (uintstatus & VPOSTB_BUS_ERROR_INT)
      vpostBUS_ERROR_ISR();

#ifdef ECOS
	return CYG_ISR_HANDLED;
#endif
}

static void vpostEnable_Int(void)
{
#ifdef ECOS
    cyg_interrupt_create(IRQ_LCD, 1, 0, vpostIntHandler, NULL, &_tSAMSUNG_80_18BIT.vpost_int_handle, &_tSAMSUNG_80_18BIT.vpost_int_holder);
    cyg_interrupt_attach(vpost_int_handle);
    cyg_interrupt_unmask(IRQ_LCD);
#else
    sysInstallISR(IRQ_LEVEL_1, IRQ_LCD, (PVOID)vpostIntHandler);
    /* enable VPOST interrupt */
    sysEnableInterrupt(IRQ_LCD);
#endif
    writew(REG_LCM_DCCS,readw(REG_LCM_DCCS) | VPOSTB_DISP_INT_EN);
    writew(REG_LCM_INT_CS,readw(REG_LCM_INT_CS) | VPOSTB_UNDERRUN_EN | VPOSTB_DISP_F_EN);
}



INT vpostOSDInit_SAMSUNG_80_18BIT(UINT16 ucOSDSrcType,UINT16 usxstart,UINT16 usystart,
											UINT16 usxend,UINT16 usyend,UINT16 usOSDPicWidth)
{
	INT retValue=0;

	vpostSetOSDSrc(ucOSDSrcType);
	retValue = vpostSetOSDBuffer();
	if (retValue<0)
		return retValue;//printf("illegal memory allocation\n");
		
	
    /*
    if (ucOSDSrcType != 0)
		writew(REG_LCM_DCCS,readw(REG_LCM_DCCS) | ucOSDSrcType);
    else
		writew(REG_LCM_DCCS,readw(REG_LCM_DCCS) & 0xffff0fff);//clear OSD SRC setting	
	*/
    vpostOSDSetWindow(usxstart,usystart,usxend,usyend);
     
	writew(REG_LCM_OSD_FBCTRL,0);//clear OSD STRIDE,FF setting
    if ((ucOSDSrcType==OSD_SRC_RGB888)||(ucOSDSrcType==OSD_SRC_RGB666))
    {
		writew(REG_LCM_OSD_FBCTRL,(usOSDPicWidth<<16) | usOSDPicWidth); //OSDFF~OSD_STRIDE
    }
    else if (ucOSDSrcType==OSD_SRC_RGB332)
    {
    	writew(REG_LCM_OSD_FBCTRL,((usOSDPicWidth/4)<<16) | (usOSDPicWidth/4)); //OSDFF~OSD_STRIDE
    }
    else{
        writew(REG_LCM_OSD_FBCTRL,((usOSDPicWidth/2)<<16) | (usOSDPicWidth/2)); //OSDFF~OSD_STRIDE
    }
    //vpostOSDScalingCtrl(1,0,0);
    
    return 0;
}






static VOID vpostInitialFunction1(UINT8 ROT90)
{
	vpostLCDWriteAddr(0x01);
	vpostLCDWriteData(0x200);
	vpostLCDWriteAddr(0x02);	
	vpostLCDWriteData(0x0700);	        
	vpostLCDWriteAddr(0x03);
	if (ROT90==1)
		vpostLCDWriteData(0x0008);				//k04264-1
		//vpostLCDWriteData(0x0028);				//k04264-1
	else
		vpostLCDWriteData(0x0220);				//k04264-1
	vpostLCDWriteAddr(0x04);	
	vpostLCDWriteData(0x0000);        	
	vpostLCDWriteAddr(0x08);
	vpostLCDWriteData(0x0626);
	vpostLCDWriteAddr(0x09);
	vpostLCDWriteData(0x0000);
	vpostLCDWriteAddr(0x0b);	
	vpostLCDWriteData(0x0000);        	
	vpostLCDWriteAddr(0x0c);
	vpostLCDWriteData(0x0000);
	vpostLCDWriteAddr(0x0f);
	vpostLCDWriteData(0x0000);
	Delay(400);
}
static VOID vpostPowerSettingFunction()
{
	vpostLCDWriteAddr(0x07);	
	vpostLCDWriteData(0x0008);	    
	vpostLCDWriteAddr(0x11);	
	vpostLCDWriteData(0x0067);	    
	vpostLCDWriteAddr(0x12);	
	vpostLCDWriteData(0x0f09);
	vpostLCDWriteAddr(0x13);	
	vpostLCDWriteData(0x121b);	    
	vpostLCDWriteAddr(0x10);	
	vpostLCDWriteData(0x0010);	    
	vpostLCDWriteAddr(0x12);	
	vpostLCDWriteData(0x0f19);
	Delay(8000);
	vpostLCDWriteAddr(0x13);	
	vpostLCDWriteData(0x321b);	    
	vpostLCDWriteAddr(0x11);	
	vpostLCDWriteData(0x0297);	
	vpostLCDWriteAddr(0x10);	
	vpostLCDWriteData(0x0210);	
	vpostLCDWriteAddr(0x12);	
	vpostLCDWriteData(0x3f19);
	Delay(12000);
}
static VOID vpostInitialFunction2()
{
	vpostLCDWriteAddr(0x23);	
	vpostLCDWriteData(0x0000);	    
	vpostLCDWriteAddr(0x24);	
	vpostLCDWriteData(0x0000);	    
	vpostLCDWriteAddr(0x50);	
	vpostLCDWriteData(0x0000);		
	vpostLCDWriteAddr(0x51);	
	vpostLCDWriteData(0x007f);		
	vpostLCDWriteAddr(0x52);	
	vpostLCDWriteData(0x0000);	    	
	vpostLCDWriteAddr(0x53);	
	vpostLCDWriteData(0x009f);	    
	vpostLCDWriteAddr(0x60);	
	vpostLCDWriteData(0x9300);		
	vpostLCDWriteAddr(0x61);	
	vpostLCDWriteData(0x0001);		
	vpostLCDWriteAddr(0x68);	
	vpostLCDWriteData(0x0000);		
	vpostLCDWriteAddr(0x69);	
	vpostLCDWriteData(0x009f);	    	
	vpostLCDWriteAddr(0x6a);	
	vpostLCDWriteData(0x0000);	    	
	vpostLCDWriteAddr(0x70);	
	vpostLCDWriteData(0x8b14);	    
	vpostLCDWriteAddr(0x71);	
	vpostLCDWriteData(0x0001);		
	vpostLCDWriteAddr(0x78);	
	vpostLCDWriteData(0x00a0);		
	vpostLCDWriteAddr(0x79);	
	vpostLCDWriteData(0x00ff);	    
	vpostLCDWriteAddr(0x7a);	
	vpostLCDWriteData(0x0000);	    
	vpostLCDWriteAddr(0x80);	
	vpostLCDWriteData(0x0000);
	vpostLCDWriteAddr(0x81);	
	vpostLCDWriteData(0x0000);	    
	vpostLCDWriteAddr(0x82);	
	vpostLCDWriteData(0x0000);	    
	vpostLCDWriteAddr(0x83);	
	vpostLCDWriteData(0x0000);
	vpostLCDWriteAddr(0x84);	
	vpostLCDWriteData(0x0000);
	vpostLCDWriteAddr(0x85);	
	vpostLCDWriteData(0x0000);	    
	vpostLCDWriteAddr(0x86);	
	vpostLCDWriteData(0x0000);	    
	vpostLCDWriteAddr(0x87);	
	vpostLCDWriteData(0x0000);
	vpostLCDWriteAddr(0x88);	
	vpostLCDWriteData(0x0000);
	Delay(8000);
	vpostLCDWriteAddr(0x30);	
	vpostLCDWriteData(0x0700);	    
	vpostLCDWriteAddr(0x31);	
	vpostLCDWriteData(0x0007);	    
	vpostLCDWriteAddr(0x32);	
	vpostLCDWriteData(0x0000);
	vpostLCDWriteAddr(0x33);	
	vpostLCDWriteData(0x0100);	    
	vpostLCDWriteAddr(0x34);	
	vpostLCDWriteData(0x0707);	    
	vpostLCDWriteAddr(0x35);	
	vpostLCDWriteData(0x0007);
	vpostLCDWriteAddr(0x36);	
	vpostLCDWriteData(0x0700);	    
	vpostLCDWriteAddr(0x37);	
	vpostLCDWriteData(0x0001);	    
	vpostLCDWriteAddr(0x38);	
	vpostLCDWriteData(0x1800);
	vpostLCDWriteAddr(0x39);	
	vpostLCDWriteData(0x0007);
	Delay(400);
	vpostLCDWriteAddr(0x40);	
	vpostLCDWriteData(0x0700);	    
	vpostLCDWriteAddr(0x41);	
	vpostLCDWriteData(0x0007);
	vpostLCDWriteAddr(0x42);	
	vpostLCDWriteData(0x0000);	    
	vpostLCDWriteAddr(0x43);	
	vpostLCDWriteData(0x0100);	    
	vpostLCDWriteAddr(0x44);	
	vpostLCDWriteData(0x0707);
	vpostLCDWriteAddr(0x45);	
	vpostLCDWriteData(0x0007);
	vpostLCDWriteAddr(0x46);	
	vpostLCDWriteData(0x0700);	    
	vpostLCDWriteAddr(0x47);	
	vpostLCDWriteData(0x0001);
	vpostLCDWriteAddr(0x48);	
	vpostLCDWriteData(0x1800);
	vpostLCDWriteAddr(0x49);	
	vpostLCDWriteData(0x0007);
	Delay(400);
}

static VOID vpostDisplayOnFunction(UINT8 ROT90)
{
	vpostLCDWriteAddr(0x07);	
	vpostLCDWriteData(0x0301);
	Delay(12000);
	vpostLCDWriteAddr(0x07);	
	vpostLCDWriteData(0x0321);	    
	vpostLCDWriteAddr(0x07);	
	vpostLCDWriteData(0x0323);	
	Delay(12000);
	vpostLCDWriteAddr(0x07);	
	vpostLCDWriteData(0x0333);
	Delay(8000);    
	vpostLCDWriteAddr(0x20);   
	vpostLCDWriteData(0x007f);
	vpostLCDWriteAddr(0x21);  
	if (ROT90==0)
		vpostLCDWriteData(0x0000);	
	else
		vpostLCDWriteData(0x009f);
	vpostLCDWriteAddr(0x22);
}

static VOID vpostSetCRTC_SAMSUNG_80_18BIT(UINT16 usHorizontal,UINT16 usVertical,UINT16 ucVASrcType,UINT16 usPicWidth)
{   
	writew(REG_LCM_CRTC_SIZE,(((usVertical + CRTC_Retrace_HOffset) << 16) | usHorizontal) 
								+ CRTC_Retrace_Offset	); //CRTC_SIZE

	writew(REG_LCM_CRTC_DEND,(usVertical << 16) | usHorizontal); //CRTC_DEND

	writew(REG_LCM_CRTC_HR,((usHorizontal + 15) << 16) | (usHorizontal + 10)); //CRTC_HR

    writew(REG_LCM_CRTC_HSYNC,((usHorizontal + CRTC_Retrace_Offset - 5) << 16)
    							| (usHorizontal + CRTC_Retrace_Offset - 10)); //CRTC_HSYNC
	writew(REG_LCM_CRTC_VR,((usVertical + CRTC_Retrace_HOffset/2) << 16)
    						| (usVertical + CRTC_Retrace_HOffset/4)); //CRTC_VR
    if ((ucVASrcType==VA_SRC_RGB888)||(ucVASrcType==VA_SRC_RGB666))
    {
		writew(REG_LCM_VA_FBCTRL,inpw(REG_LCM_VA_FBCTRL) &~0x7ff07ff | (usPicWidth << 16) | usPicWidth); //VAFF~VA_STRIDE
	}
	else
    {
		writew(REG_LCM_VA_FBCTRL,inpw(REG_LCM_VA_FBCTRL) &~0x7ff07ff | ((usPicWidth/2) << 16) | (usPicWidth/2)); //VAFF~VA_STRIDE
    }

}

VOID vpostSetup_SAMSUNG_80_18BIT(UINT8 ROT90)
{
	/* output-disable,video disable */
	writew(REG_LCM_DCCS,readw(REG_LCM_DCCS)& ~(VPOSTB_DISP_OUT_EN | VPOSTB_VA_EN));
	writew(REG_LCM_DCCS,readw(REG_LCM_DCCS) | VPOSTB_DISP_OUT_EN); //display_out-enable
	Delay(4000);
	vpostInitialFunction1(ROT90);
    vpostPowerSettingFunction();
    vpostInitialFunction2();
    vpostDisplayOnFunction(ROT90);
}

INT vpostLCMInit_SAMSUNG_80_18BIT(VA_CB_FUNC_T *fnCallBack,UINT16 ucVASrcType,UINT8 ucVADisMode,UINT16 usPicWidth,UINT8 ucROT90)
{
	UINT32 VA_FF;
	UINT32 VA_Sride;
	/* initialize the structure of display device */
	_tSAMSUNG_80_18BIT.usDevWidth = 128;
	_tSAMSUNG_80_18BIT.usDevHeight = 160;
	_tSAMSUNG_80_18BIT.uCmdLow = VPOSTB_CMDLOW;
	_tSAMSUNG_80_18BIT.ucCmd16t18 = VPOSTB_CM16t18LOW;
	_tSAMSUNG_80_18BIT.uCmdBusWidth = VPOSTB_CMD16;
	_tSAMSUNG_80_18BIT.uDataBusWidth = VPOSTB_DATA16or18 | VPOSTB_IM256K_9or18;
	_tSAMSUNG_80_18BIT.ucMPU_Mode = VPOSTB_MPU80;
	_tSAMSUNG_80_18BIT.uMPU_ColorMode = VPOSTB_COLORTYPE_256K;
	_tSAMSUNG_80_18BIT.ucDeviceType = VPOSTB_DEVICE_MPU;
	_tSAMSUNG_80_18BIT.fnDisplayCallBack = fnCallBack;
	
	//outpw(REG_MISCR,0x00);// bridge-mode 0
	//outpw(REG_MISCR,0x01);// bridge-mode 1
	
	/* reset display engine */
	outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | VPOSTB_ENG_RST);
	Delay(100);
	outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) & ~VPOSTB_ENG_RST);
	Delay(100);
		
	/* set the display buffer (fetch from VA_BADDR0, if at single buffer mode)*/
	if (vpostSetVABuffer()<0)
		return ERR_NULL_BUF;
		
	/* set display mode */
	vpostSetDisplayMode(ucVADisMode);
	vpostSetVASrc(ucVASrcType);
	/* set display video source format */
	/*
	if (ucVASrcType!=0)
		outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | ucVASrcType);
	else
		outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) & ~(7<<8));
	*/
	//18-bit,256k,80mode,mpu-based,cmd18-16L0
	vpostSetDeviceCtrl(_tSAMSUNG_80_18BIT);
	/*
	outpw(REG_LCM_DEV_CTRL,0xE0);//set default value
	writew(REG_LCM_DEV_CTRL,inpw(REG_LCM_DEV_CTRL) | _tSAMSUNG_80_18BIT.uCmdLow 
												   | _tSAMSUNG_80_18BIT.ucCmd16t18
												   | _tSAMSUNG_80_18BIT.uCmdBusWidth
												   | _tSAMSUNG_80_18BIT.uDataBusWidth
												   | _tSAMSUNG_80_18BIT.ucMPU_Mode
												   | _tSAMSUNG_80_18BIT.uMPU_Color_Mode
												   | _tSAMSUNG_80_18BIT.ucDeviceType );
	*/

	if (ucROT90)
		vpostSetCRTC_SAMSUNG_80_18BIT(_tSAMSUNG_80_18BIT.usDevHeight,_tSAMSUNG_80_18BIT.usDevWidth,
						ucVASrcType,usPicWidth);
	else						
		vpostSetCRTC_SAMSUNG_80_18BIT(_tSAMSUNG_80_18BIT.usDevWidth,_tSAMSUNG_80_18BIT.usDevHeight,
						ucVASrcType,usPicWidth);

	/* set video stream frame buffer control */
	VA_FF = (plcdformatex->nScreenWidth)*(nBytesPixel)/4;//word unit
    VA_Sride = (plcdformatex->nScreenWidth)*(nBytesPixel)/4;//word unit
    outpw(REG_LCM_VA_FBCTRL,inpw(REG_LCM_VA_FBCTRL) &~0x7ff07ff | (VA_FF<<16) | VA_Sride);
    
	vpostSetup_SAMSUNG_80_18BIT(ucROT90);
	vpostVAScalingCtrl(1,0,1,0,VA_SCALE_INTERPOLATION);
	vpostVAStartTrigger();   // add by smf
	//vpostEnable_Int();
	return 0;
}



#endif	/* HAVE_SAMSUNG_80_18IT */